/*
 * Copyright (c) 2024 Huawei Technologies Co., Ltd.
 * openUBMC is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *         http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 */

#include <gtest/gtest.h>
#include <mc/engine.h>
#include <mc/singleton.h>
#include <mc/string.h>
#include <mc/format.h>
#include <test_utilities/test_base.h>
#include <devmon/driver_abi.h>
#include <dlfcn.h>
#include <sstream>
#include <iomanip>
#include <algorithm>
#include <cctype>

#include "complex/chip.h"
#include "smbus/std_smbus.h"
#include "smbus/smbus.h"

// 引入打桩的chip
#include "chip_mock.h"

namespace dev {
namespace smbus_test {

    // 辅助函数：将字符转换为十六进制字符串
    std::string to_hex(char c) {
        std::stringstream ss;
        ss << std::hex << std::setfill('0') << std::setw(2) 
           << static_cast<unsigned int>(static_cast<unsigned char>(c));
        return ss.str();
    }

    // 辅助函数：将字符串转换为十六进制字符串
    std::string to_hex(const std::string& data) {
        if (data.empty()) {
            return "";
        }
        
        std::stringstream ss;
        ss << std::hex << std::setfill('0') << std::uppercase;
        for (unsigned char byte : data) {
            ss << std::setw(2) << static_cast<int>(byte) << " ";
        }
        return ss.str();
    }

    // 辅助函数：将多个字符连接并转换为十六进制字符串
    std::string to_hex(std::initializer_list<char> chars) {
        if (chars.size() == 0) {
            return "";
        }
        
        std::string data(chars.begin(), chars.end());
        return to_hex(data);
    }

    // 辅助函数：将字节数组转换为十六进制字符串
    std::string to_hex(const uint8_t* data, size_t length) {
        if (!data || length == 0) {
            return "";
        }
        
        std::stringstream ss;
        ss << std::hex << std::setfill('0') << std::uppercase;
        for (size_t i = 0; i < length; ++i) {
            ss << std::setw(2) << static_cast<int>(data[i]);
        }
        return ss.str();
    }

    // 辅助函数：将十六进制字符串转换回字节数组
    std::string from_hex(const std::string& hex_str) {
        if (hex_str.empty() || hex_str.length() % 2 != 0) {
            return "";
        }
        
        std::string result;
        result.reserve(hex_str.length() / 2);
        
        for (size_t i = 0; i < hex_str.length(); i += 2) {
            std::string byte_str = hex_str.substr(i, 2);
            try {
                char byte = static_cast<char>(std::stoi(byte_str, nullptr, 16));
                result.push_back(byte);
            } catch (const std::exception&) {
                return ""; // 转换失败返回空字符串
            }
        }
        
        return result;
    }

    // 辅助函数：比较两个十六进制字符串是否相等，忽略大小写
    bool hex_equal(const std::string& hex1, const std::string& hex2) {
        if (hex1.length() != hex2.length()) {
            return false;
        }
        
        std::string upper1 = hex1;
        std::string upper2 = hex2;
        std::transform(upper1.begin(), upper1.end(), upper1.begin(), ::toupper);
        std::transform(upper2.begin(), upper2.end(), upper2.begin(), ::toupper);
        
        return upper1 == upper2;
    }

    class test_service : public mc::engine::service {
    public:
        test_service() : mc::engine::service("bmc.kepler.devmon") {
        }
    };

    class engine_test : public mc::test::TestWithEngine {
    protected:
        static void SetUpTestSuite() {
            TestWithEngine::SetUpTestSuite();
            m_service.init();
            m_service.start();
        }

        static void TearDownTestSuite() {
            // 清理所有注册的对象
            m_created_objects.clear();
            
            m_service.stop();
            if (m_driver_handle != nullptr) {
                dlclose(m_driver_handle);
                m_driver_handle = nullptr;
            }
            TestWithEngine::TearDownTestSuite();
        }

        void SetUp() override {
            // 底层驱动打桩会自动管理内存，无需手动清理
        }

        void TearDown() override {
            // 底层驱动打桩会自动管理内存，无需手动清理
        }

        complex_object* create_dbus_object(std::string_view path, mc::mutable_dict& csr_object, mc::dict& connector) {
            // auto device_driver = m_devices["Complex"];
            // auto obj = static_cast<complex_object*>(device_driver->ctor(&m_service, "test_complex_object"));

            auto obj = mc::make_shared<complex_object>();
            if (obj == nullptr) {
                return nullptr;
            }
            // 调用对象的 init 方法
            bool ret = obj->init(csr_object, connector);

            int         object_id = m_object_id++;
            std::string object_name =
                mc::fmt::format_v("%s_%d", obj->get_class_name().data(), object_id);

            obj->set_object_path(path);
            obj->set_object_name(object_name);
            obj->set_position("0101");
            m_service.register_object(obj);
            
            // 保存对象引用以确保生命周期管理
            m_created_objects.push_back(obj);
            
            return obj.get();
        };

        static void* m_driver_handle;
        static std::unordered_map<std::string, std::shared_ptr<device_driver_t>> m_devices;
        static test_service m_service;
        static int m_object_id;
        static std::vector<mc::shared_ptr<complex_object>> m_created_objects;
    };

    void* engine_test::m_driver_handle = nullptr;
    std::unordered_map<std::string, std::shared_ptr<device_driver_t>> engine_test::m_devices;
    test_service engine_test::m_service;
    int engine_test::m_object_id = 0;
    std::vector<mc::shared_ptr<complex_object>> engine_test::m_created_objects;


    TEST_F(engine_test, test_std_smbus_construct_request_data_test_1) {
        auto smbus_obj = mc::make_shared<std_smbus>(nullptr);
        
        // 初始化smbus对象
        auto params = mc::mutable_dict{
            {"BufferLen", 256},
            {"McuAddress", 0x20}
        };
        smbus_obj->init(params);

        // 构建请求参数
        mc::mutable_dict request = mc::mutable_dict{
            {"opcode", 0x104},
            {"data_written", 0},
            {"len", 0x06},
            {"data", ""},
            {"arg", 0},
        };
        
        // 调用construct_request_data方法
        auto request_data = smbus_obj->construct_request_data(request);
        
        // 验证返回的数据不为空
        EXPECT_FALSE(request_data.empty());
        
        // 构建期望的十六进制数据
        // 根据smbus_request_t结构体：count(1) + lun(1) + arg(1) + opcode(2) + offset(4) = 9字节
        std::string expected_hex = to_hex({
            '\x0C',  // count: 2 + 0 (write_data.length) = 2
            '\x80',  // lun: 0 (未完成写入)
            '\x00',  // arg: 0
            '\x04',  // opcode: 0x104 低字节
            '\x01',  // opcode: 0x104 高字节
            '\x00',  // offset: 0 低字节
            '\x00',  // offset: 0
            '\x00',  // offset: 0
            '\x00',  // offset: 0 高字节
            '\x06',  
            '\x00',
            '\x00',
            '\x00',
        });
        
        // 将实际数据转换为十六进制进行比较
        std::string actual_hex = to_hex(request_data);
        
        // 验证数据长度
        EXPECT_EQ(request_data.length(), 13) << "Expected 13 bytes, got " << request_data.length();
        
        // 验证十六进制数据
        EXPECT_EQ(actual_hex, expected_hex) << "Expected: " << expected_hex << ", Got: " << actual_hex;
        
        // 验证opcode字段
        uint16_t opcode = static_cast<unsigned char>(request_data[3]) | 
                         (static_cast<unsigned char>(request_data[4]) << 8);
        EXPECT_EQ(opcode, 0x104) << "Expected opcode 0x104, got 0x" << std::hex << opcode;
        
        // 验证length字段
        uint16_t length = static_cast<unsigned char>(request_data[9]) | 
                         (static_cast<unsigned char>(request_data[10]) << 8);
        EXPECT_EQ(length, 0x06) << "Expected length 0x06, got 0x" << std::hex << length;
    }

    TEST_F(engine_test, test_std_smbus_construct_request_data_test_2) {
        auto smbus_obj = mc::make_shared<std_smbus>(nullptr);
        
        // 初始化smbus对象
        auto params = mc::mutable_dict{
            {"BufferLen", 256},
            {"McuAddress", 0x20}
        };
        smbus_obj->init(params);

        // 构建请求参数
        mc::mutable_dict request = mc::mutable_dict{
            {"opcode", 0x104},
            {"data_written", 0x05},
            {"len", 0x05},
            {"data", std::string(0x10, '\x02')},
            {"arg", 0x05},
        };
        
        // 构建期望的十六进制数据
        std::string header_hex = to_hex({
            '\x11',  // count: 12 + 5 (write_data.length) = 17 = 0x11
            '\x00',  // lun: 0 (未完成写入，因为data_written + len = 10 < data.length = 16)
            '\x05',  // arg: 0x05
            '\x04', '\x01',  // opcode: 0x104
            '\x05', '\x00', '\x00', '\x00',  // offset: 0x05
            '\x05', '\x00', '\x00', '\x00',  // length: 0x05
        });
        
        std::string data_hex = to_hex(std::string(0x05, '\x02'));
        std::string expected_hex = header_hex + data_hex;

        auto request_data = smbus_obj->construct_request_data(request);
        std::string actual_hex = to_hex(request_data);
        
        EXPECT_EQ(actual_hex, expected_hex) << "Expected: " << expected_hex << ", Got: " << actual_hex;
    }

    TEST_F(engine_test, test_std_smbus_unpack_response_data_test_1) {
        auto smbus_obj = mc::make_shared<std_smbus>(nullptr);
        
        // 初始化smbus对象
        auto params = mc::mutable_dict{
            {"BufferLen", 256},
            {"McuAddress", 0xD4}
        };
        smbus_obj->init(params);
        // 构建响应数据

        const uint8_t raw_data[66] = {
            0x0C, 
            0x00, 0x00, 
            0x10, 0x00, 
            0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 
            // data 缺省为空
            0x9C,
            // ... 剩余字节 ...
        };
        std::string rsp_bin(reinterpret_cast<const char*>(raw_data), 66);
        // 仅用于调试，使用cout打印crc_input，每个字节用空格隔开
        {
            std::cout << "rsp_bin: ";
            for (size_t i = 0; i < rsp_bin.size(); ++i) {
                printf("%02X", static_cast<uint8_t>(rsp_bin[i]));
                if (i != rsp_bin.size() - 1) {
                    std::cout << " ";
                }
            }
            std::cout << std::endl;
        }
        // 调试之后要记得删除

        auto expect_rsp = mc::mutable_dict{
            {"count", 0x0C},
            {"error_code", 0x0000},
            {"opcode", 0x0010},
            {"total_length", 0x0000},
            {"length", 0x0000},
            {"data", ""},
        };
        auto [ok, rsp] = smbus_obj->unpack_response_data(rsp_bin, 0);
        std::cout << "sucess process unpack_response_data" << std::endl;
        EXPECT_TRUE(ok);
        EXPECT_EQ(rsp["count"].as<uint8_t>(), expect_rsp["count"].as<uint8_t>());
        EXPECT_EQ(rsp["error_code"].as<uint16_t>(), expect_rsp["error_code"].as<uint16_t>());
        EXPECT_EQ(rsp["opcode"].as<uint16_t>(), expect_rsp["opcode"].as<uint16_t>());
        EXPECT_EQ(rsp["total_length"].as<uint32_t>(), expect_rsp["total_length"].as<uint32_t>());
        EXPECT_EQ(rsp["length"].as<uint32_t>(), expect_rsp["length"].as<uint32_t>());
        EXPECT_EQ(rsp["data"].as<std::string>(), expect_rsp["data"].as<std::string>());
    }

    TEST_F(engine_test, test_std_smbus_unpack_response_data_test_with_crc) {
        auto smbus_obj = mc::make_shared<std_smbus>(nullptr);
        
        // 初始化smbus对象
        auto params = mc::mutable_dict{
            {"BufferLen", 256},
            {"McuAddress", 0xD4}
        };
        smbus_obj->init(params);
        
        const uint8_t raw_data[66] = {
            0x15, 
            0x00, 0x00, 
            0x04, 0x04, 
            0x2D, 0x00, 0x00, 0x00,
            0x09, 0x00, 0x00, 0x00, 
            0x05, 0x00, 0x10 ,0x00 ,0x15, 0x5d , 0x50, 0x36, 0x14,
            0x2C,
            // ... 剩余字节 ...
        };
        std::string rsp_bin(reinterpret_cast<const char*>(raw_data), 66);
        // 仅用于调试，使用cout打印crc_input，每个字节用空格隔开
        {
            std::cout << "rsp_bin: ";
            for (size_t i = 0; i < rsp_bin.size(); ++i) {
                printf("%02X", static_cast<uint8_t>(rsp_bin[i]));
                if (i != rsp_bin.size() - 1) {
                    std::cout << " ";
                }
            }
            std::cout << std::endl;
        }
        // 调试之后要记得删除

        auto expect_rsp = mc::mutable_dict{
            {"count", 0x15},
            {"error_code", 0x0000},
            {"opcode", 0x0404},
            {"total_length", 0x002D},
            {"length", 0x0009},
            {"data", std::string("\x05\x00\x10\x00\x15\x5d\x50\x36\x14", 9)},
        };
        auto [ok, rsp] = smbus_obj->unpack_response_data(rsp_bin, 0);
        std::cout << "sucess process unpack_response_data" << std::endl;
        EXPECT_TRUE(ok);
        EXPECT_EQ(rsp["count"].as<uint8_t>(), expect_rsp["count"].as<uint8_t>());
        EXPECT_EQ(rsp["error_code"].as<uint16_t>(), expect_rsp["error_code"].as<uint16_t>());
        EXPECT_EQ(rsp["opcode"].as<uint16_t>(), expect_rsp["opcode"].as<uint16_t>());
        EXPECT_EQ(rsp["total_length"].as<uint32_t>(), expect_rsp["total_length"].as<uint32_t>());
        EXPECT_EQ(rsp["length"].as<uint32_t>(), expect_rsp["length"].as<uint32_t>());
        EXPECT_EQ(to_hex(rsp["data"].as<std::string>()), to_hex(expect_rsp["data"].as<std::string>()));
    }

    TEST_F(engine_test, test_std_smbus_send_and_receive_test_1) {
        auto ref_chip = mc::make_shared<mock_chip::ChipMock>();
        auto smbus_obj = mc::make_shared<std_smbus>(nullptr);
        auto params = mc::mutable_dict{
            {"BufferLen", 64},
            {"McuAddress", 0xD4}
        };
        smbus_obj->init(params);
        // 注册WriteRead方法
        smbus_obj->register_ComboWriteRead_method([&](const uint32_t& write_offset, const std::vector<uint8_t>& write_buffer,
                                        const uint32_t& read_offset, const uint32_t& read_length) {
            return ref_chip->m_interface_chip.BlockIOComboWriteRead(write_offset, write_buffer, read_offset, read_length);
        });

        mc::mutable_dict request = mc::mutable_dict{
            {"opcode", 0x0404},
            {"data", std::string("")},
            {"arg", 0x00},
        };

        auto request_data = smbus_obj->send_request(request);
        auto expect_data = std::string(
            "\x05\x00\x10\x00\x15\x5d\x50\x36\x14"
            "\x05\x00\x10\x00\x15\x5d\x50\x36\x14"
            "\x05\x00\x10\x00\x15\x5d\x50\x36\x14"
            "\x05\x00\x10\x00\x15\x5d\x50\x36\x14"
            "\x05\x00\x10\x00\x15\x5d\x50\x36\x14", 45); 
        std::cout << "request_data: " << to_hex(request_data) << std::endl;
        std::cout << "expect_data: " << to_hex(expect_data) << std::endl;
        EXPECT_EQ(request_data, expect_data);
    }

    TEST_F(engine_test, test_std_smbus_send_and_receive_test_2) {
        auto ref_chip = mc::make_shared<mock_chip::ChipMock>();
        auto smbus_obj = mc::make_shared<std_smbus>(nullptr);
        auto params = mc::mutable_dict{
            {"BufferLen", 64},
            {"McuAddress", 0xD4}
        };
        smbus_obj->init(params);
        // 注册WriteRead方法
        smbus_obj->register_ComboWriteRead_method([&](const uint32_t& write_offset, const std::vector<uint8_t>& write_buffer,
                                        const uint32_t& read_offset, const uint32_t& read_length) {
            return ref_chip->m_interface_chip.BlockIOComboWriteRead(write_offset, write_buffer, read_offset, read_length);
        });

        mc::mutable_dict request = mc::mutable_dict{
            {"opcode", 0x10},
            {"data", std::string("a lot of data to send so we need to send multiple times")},
            {"arg", 0x00},
        };

        auto request_data = smbus_obj->send_request(request);
        auto expect_data = std::string(""); 
        std::cout << "request_data: " << to_hex(request_data) << std::endl;
        std::cout << "expect_data: " << to_hex(expect_data) << std::endl;
        EXPECT_EQ(request_data, expect_data);
    }

    TEST_F(engine_test, test_smbus_unpack_request) {
        auto smbus_obj = mc::make_shared<smbus>(nullptr);
        auto params = mc::mutable_dict{
            {"BufferLen", 32},
            {"McuAddress", 0xD4}
        };
        smbus_obj->init(params);
        std::vector<uint8_t> data = {0x00, 0x00, 0x04, 0x01, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x10, 0x01,
                                     0x24, 0x35, 0xA8, 0x3E, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
        auto track_request = mc::mutable_dict{
            {"arg" , 0},
            {"data", ""},
            {"data_object_index", 0},
            {"data_written", 0},
            {"expect_data_len", 2},
            {"len", 2},
            {"max_frame_len" , 16},
            {"offset_invalid", false},
            {"opcode", 0x0104}
        };
        
        auto [ok, rsp] = smbus_obj->_unpack_request(data, track_request);
        EXPECT_TRUE(ok);
        EXPECT_EQ(rsp["opcode"].as<uint16_t>(), 0x0104);
        std::string expected_data = std::string("\x10\x01", 2);
        EXPECT_EQ(rsp["data"].as<std::string>(), expected_data);
    }

    TEST_F(engine_test, test_smbus_with_mock_chip) {
        auto ref_chip = mc::make_shared<mock_chip::ChipMock>();
        auto smbus_obj = mc::make_shared<smbus>(nullptr);
        auto params = mc::mutable_dict{
            {"BufferLen", 64},
            {"McuAddress", 0xD4}
        };
        smbus_obj->init(params);
        // 注册WriteRead方法
        smbus_obj->register_WriteRead_method([&](const std::vector<uint8_t>& data, uint32_t len) {
            return ref_chip->m_interface_chip.BlockIOWriteRead(data, len);
        });

        auto request_data = std::vector<uint8_t>({0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x57, 0xd8, 0x14});
        auto request_bin = std::string(request_data.begin(), request_data.end());
        auto [ok, rsp] = smbus_obj->send_and_receive(request_bin, 16);
        std::vector<uint8_t> expected = {0x00, 0x00, 0x05, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x11, 0x45, 0x02, 0x21, 0x29, 0xEF, 0xA4};
        // 剩下的用0xFF填充
        for (int i = expected.size(); i < 64; i++) {
            expected.push_back(0xFF);
        }   
        EXPECT_TRUE(ok);
        EXPECT_EQ(rsp, expected);
    }

    TEST_F(engine_test, test_smbus_construct_request_data_test_1) {
        auto smbus_obj = mc::make_shared<smbus>(nullptr);
        auto params = mc::mutable_dict{
            {"BufferLen", 256},
            {"McuAddress", 0xD4}
        };
        smbus_obj->init(params);

        auto request = mc::mutable_dict{
            {"opcode", 0x05},
            {"data_written", 0x00},
            {"len", 0x03},
        };
        auto request_data = smbus_obj->construct_request_data(request);
        std::string expected_hex = to_hex({
            '\x00', '\x00', '\x05', '\x00', '\x00', '\x00', '\x00', '\x00', '\x03', '\x00', '\x00', '\x00', '\x04', '\x57', '\xd8', '\x14'
        });
        std::string actual_hex = to_hex(request_data);
        EXPECT_EQ(actual_hex, expected_hex);
    }

    TEST_F(engine_test, test_smbus_unpack_response_data_test) {
        auto smbus_obj = mc::make_shared<smbus>(nullptr);
        auto params = mc::mutable_dict{
            {"BufferLen", 32},
            {"McuAddress", 0xD4}
        };
        smbus_obj->init(params);
        auto rsp_bin = std::string(
            "\x00\x00" // error_code
            "\x04\x04" // opcode
            "\x2D\x00\x00\x00" // total_length
            "\x09\x00\x00\x00" // length
            "\x05\x00\x10\x00\x15\x5d\x50\x36\x14" // data
            "\x00\x00\x00\x00\x00\x00\x00" // 填充
            "\x4B\x49\xEF\xB4" // crc32
        , 32);
        auto [ok, rsp] = smbus_obj->unpack_response_data(rsp_bin, 0);
        EXPECT_TRUE(ok);
        EXPECT_EQ(rsp["error_code"].as<uint16_t>(), 0x0000);
        EXPECT_EQ(rsp["opcode"].as<uint16_t>(), 0x0404);
        EXPECT_EQ(rsp["total_length"].as<uint32_t>(), 0x002D);
        EXPECT_EQ(rsp["length"].as<uint32_t>(), 0x0009);
        std::string expected_data = std::string("\x05\x00\x10\x00\x15\x5d\x50\x36\x14", 9);
        EXPECT_EQ(rsp["data"].as<std::string>(), expected_data);
    }

    TEST_F(engine_test, test_smbus_unpack_response_data_test_2) {
        auto smbus_obj = mc::make_shared<smbus>(nullptr);
        auto params = mc::mutable_dict{
            {"BufferLen", 32},
            {"McuAddress", 0xD4}
        };
        smbus_obj->init(params);
        auto rsp_bin = std::string(
            "\x00\x00" // error_code
            "\x04\x01" // opcode 
            "\x02\x00\x00\x00"
            "\x02\x00\x00\x00"
            "\x10\x01" // data
            "\x24\x35\xA8\x3E" // crc32
            "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" // 填充
        , 28);
        auto [ok, rsp] = smbus_obj->unpack_response_data(rsp_bin, 2);
        EXPECT_TRUE(ok);
        EXPECT_EQ(rsp["error_code"].as<uint16_t>(), 0x0000);
        EXPECT_EQ(rsp["opcode"].as<uint16_t>(), 0x0104);
        EXPECT_EQ(rsp["total_length"].as<uint32_t>(), 0x0002);
        EXPECT_EQ(rsp["length"].as<uint32_t>(), 0x0002);
        std::string expected_data = std::string("\x10\x01", 2);
        EXPECT_EQ(rsp["data"].as<std::string>(), expected_data);
    }

    TEST_F(engine_test, test_smbus_can_send) {
        auto ref_chip = mc::make_shared<mock_chip::ChipMock>();
        auto smbus_obj = mc::make_shared<smbus>(nullptr);
        auto params = mc::mutable_dict{
            {"BufferLen", 32},
            {"McuAddress", 0xD4}
        };
        smbus_obj->init(params);
        // 注册WriteRead方法
        smbus_obj->register_WriteRead_method([&](const std::vector<uint8_t>& data, uint32_t len) {
            return ref_chip->m_interface_chip.BlockIOWriteRead(data, len);
        });

        auto request = mc::mutable_dict {
            {"expect_data_len" , 0x02},
            {"opcode" , 0x104}
        };

        auto rsp = smbus_obj->send_request(request);
        EXPECT_EQ(rsp, std::string("\x10\x01", 2));
    }

    TEST_F(engine_test, test_smbus_can_send_2) {
        auto ref_chip = mc::make_shared<mock_chip::ChipMock>();
        auto smbus_obj = mc::make_shared<smbus>(nullptr);
        auto params = mc::mutable_dict{
            {"BufferLen", 64},
            {"McuAddress", 0xD4}
        };
        std::cout << "params BufferLen: " << params["BufferLen"].as<uint32_t>() << std::endl;
        std::cout << "params McuAddress: " << params["McuAddress"].as<uint32_t>() << std::endl;
        smbus_obj->init(params);
        // 注册WriteRead方法
        smbus_obj->register_WriteRead_method([&](const std::vector<uint8_t>& data, uint32_t len) {
            return ref_chip->m_interface_chip.BlockIOWriteRead(data, len);
        });

        auto request = mc::mutable_dict {
            {"opcode" , 0x0404}
        };

        auto rsp = smbus_obj->send_request(request);
        auto expect_rsp = std::string("\x00\x00\x00\xAC\xDC\xCA\x5E\x11\xC9\x01\x00\x01"
        "\xAC\xDC\xCA\x5E\x11\xCA\x02\x00\x02\xAC\xDC\xCA\x5E\x11\xCB\x03\x00\x03"
        "\xAC\xDC\xCA\x5E\x11\xCC", 36);
        EXPECT_EQ(rsp, expect_rsp);
    }

    TEST_F(engine_test, test_smbus_can_send_3) {
        // Firmware
        auto ref_chip = mc::make_shared<mock_chip::ChipMock>();
        auto smbus_obj = mc::make_shared<smbus>(nullptr);
        auto params = mc::mutable_dict{
            {"BufferLen", 64},
            {"McuAddress", 0xD4}
        };
        std::cout << "params BufferLen: " << params["BufferLen"].as<uint32_t>() << std::endl;
        std::cout << "params McuAddress: " << params["McuAddress"].as<uint32_t>() << std::endl;
        smbus_obj->init(params);
        // 注册WriteRead方法
        smbus_obj->register_WriteRead_method([&](const std::vector<uint8_t>& data, uint32_t len) {
            return ref_chip->m_interface_chip.BlockIOWriteRead(data, len);
        });

        auto request = mc::mutable_dict {
            {"opcode" , 0x05},
            {"expect_data_len" , 3}
        };

        auto rsp = smbus_obj->send_request(request);
        auto expect_rsp = std::string("\x11\x45\x02", 3);
        EXPECT_EQ(to_hex(rsp), to_hex(expect_rsp));
    }

    TEST_F(engine_test, test_smbus_rsp_parse) {
        auto rsp = std::string("\x11\x45\x02", 3);

        struct rsp_firmeware {
            uint8_t major_ver;
            uint8_t minor_ver;
            uint8_t update_ver;
        } firmware_rsp;

        auto firmware_str = reinterpret_cast<rsp_firmeware*>(rsp.data());
        char buffer[16] = {0};
        snprintf(buffer, sizeof(buffer), "%d.%d.%d.%d", firmware_str->major_ver, firmware_str->minor_ver / 10, firmware_str->minor_ver % 10, firmware_str->update_ver);
        std::string firmware_version(buffer);
        EXPECT_EQ(firmware_version, "17.6.9.2");
    }

    TEST_F(engine_test, test_smbus_can_send_4) {
        // Firmware
        auto ref_chip = mc::make_shared<mock_chip::ChipMock>();
        auto smbus_obj = mc::make_shared<smbus>(nullptr);
        auto params = mc::mutable_dict{
            {"BufferLen", 64},
            {"McuAddress", 0xD4}
        };
        std::cout << "params BufferLen: " << params["BufferLen"].as<uint32_t>() << std::endl;
        std::cout << "params McuAddress: " << params["McuAddress"].as<uint32_t>() << std::endl;
        smbus_obj->init(params);
        // 注册WriteRead方法
        smbus_obj->register_WriteRead_method([&](const std::vector<uint8_t>& data, uint32_t len) {
            return ref_chip->m_interface_chip.BlockIOWriteRead(data, len);
        });

        auto request = mc::mutable_dict {
            {"opcode" , 0x400}
        };

        auto rsp = smbus_obj->send_request(request);
        const std::string expect_rsp(
            "\xFE\x7F\xFE\x7F"
            "\xFE\x7F\xFE\x7F",
            8
        );
        EXPECT_EQ(to_hex(rsp), to_hex(expect_rsp));
    }

    TEST_F(engine_test, test_smbus_can_send_5) {
        // Firmware
        auto ref_chip = mc::make_shared<mock_chip::ChipMock>();
        auto smbus_obj = mc::make_shared<smbus>(nullptr);
        auto params = mc::mutable_dict{
            {"BufferLen", 64},
            {"McuAddress", 0xD4}
        };
        std::cout << "params BufferLen: " << params["BufferLen"].as<uint32_t>() << std::endl;
        std::cout << "params McuAddress: " << params["McuAddress"].as<uint32_t>() << std::endl;
        smbus_obj->init(params);
        // 注册WriteRead方法
        smbus_obj->register_WriteRead_method([&](const std::vector<uint8_t>& data, uint32_t len) {
            return ref_chip->m_interface_chip.BlockIOWriteRead(data, len);
        });

        auto request = mc::mutable_dict {
            {"opcode" , 0x403}
        };

        auto rsp = smbus_obj->send_request(request);
        const std::string expect_rsp(
            "\x00\x00\x01\x01",
            4
        );
        EXPECT_EQ(to_hex(rsp), to_hex(expect_rsp));
    }

} // namespace smbus_test
} // namespace dev